
`include "defines.v"

//----------------------------------------------------------------
//Module Name : regfile.v
//Description of module:
//write_back 
//----------------------------------------------------------------
//Designer:	Tang Pengyu
//Date: 2021/07/15	  
//----------------------------------------------------------------

module regfile(
    input	clk,
	input	rst,
	
	input	[4:0]	w_addr,
	input	[`REG_DATA_LEN-1:0]	exe_data,
	
	input	[`REG_DATA_LEN-1:0]	csr_r_data,
	input	csr_r_ena,
//	input	[`REG_DATA_LEN-1:0] mem_ld_data,
	input	[`REG_DATA_LEN-1:0] load_axi_data,
	input	[`REG_DATA_LEN-1:0] load_clint_data,
	input	load_axi_en,
	input	load_clint_en,

	input	[`INST_ADDR_LEN-1:0] pc,
	input	[1:0]	wb_sel,			//10:load_mem,01:pc+4,else exe_data
	input	w_ena,
	
	input	[4:0]	r_addr1,
	output	[`REG_DATA_LEN-1:0] r_data1,
	input	r_ena1,
	
	input	[4:0]	r_addr2,
	output	[`REG_DATA_LEN-1:0]	r_data2,
	input	r_ena2
	
//	output	wire [`REG_DATA_LEN-1:0] regs_o [0:31]
    );
//32 register	
reg	[`REG_DATA_LEN-1:0] regs [0:31];
reg	[`REG_DATA_LEN-1:0]	w_data;	
wire	[`REG_DATA_LEN-1:0] mem_ld_data;
assign	mem_ld_data = ({`REG_DATA_LEN{load_axi_en}} & load_axi_data) |
					({`REG_DATA_LEN{load_clint_en}} & load_clint_data);
assign	w_data = (wb_sel == 2'b00) ? (csr_r_ena ? csr_r_data : exe_data) : 
				 ((wb_sel == 2'b01) ? (pc + 4) : 
				 ((wb_sel == 2'b10) ? mem_ld_data : 64'hxxxx_xxxx_xxxx_xxxx));

/*
always @(*)
  begin
	case(wb_sel)
		00:		w_data = exe_data;
		10:		w_data = mem_ld_data;
		01:		w_data = pc + 4;
		default:	w_data = 64'd0;
	endcase
  end
  */
//assign	w_data = wbsel ? mem_ld_data : exe_data;
//at posedge write data
	always @(posedge clk)
  begin
	if(rst)
	  begin
		regs[0] <= 64'd0;
		regs[1] <= 64'd0;
		regs[2] <= 64'd0;
		regs[3] <= 64'd0;
		regs[4] <= 64'd0;
		regs[5] <= 64'd0;
		regs[6] <= 64'd0;
		regs[7] <= 64'd0;
		regs[8] <= 64'd0;
		regs[9] <= 64'd0;
		regs[10] <= 64'd0;
		regs[11] <= 64'd0;
		regs[12] <= 64'd0;
		regs[13] <= 64'd0;
		regs[14] <= 64'd0;
		regs[15] <= 64'd0;
		regs[16] <= 64'd0;
		regs[17] <= 64'd0;
		regs[18] <= 64'd0;
		regs[19] <= 64'd0;
		regs[20] <= 64'd0;
		regs[21] <= 64'd0;
		regs[22] <= 64'd0;
		regs[23] <= 64'd0;
		regs[24] <= 64'd0;
		regs[25] <= 64'd0;
		regs[26] <= 64'd0;
		regs[27] <= 64'd0;
		regs[28] <= 64'd0;
		regs[29] <= 64'd0;
		regs[30] <= 64'd0;
		regs[31] <= 64'd0;
	  end
	else
	  begin
		if((w_ena == 1'b1) && (w_addr != 5'h00))
			regs[w_addr] <= w_data;
	  end
  end
//read data
assign r_data1 = (r_ena1 == 1'b1) ? regs[r_addr1] : 64'd0;
assign r_data2 = (r_ena2 == 1'b1) ? regs[r_addr2] : 64'd0;

/*
genvar i;
	generate
		for (i = 0; i < 32; i = i + 1) begin
			assign regs_o[i] = (w_ena & w_addr == i & i != 0) ? w_data : regs[i];
		end
	endgenerate
*/
endmodule

